package com.gitee.feizns.dynamic.concurrent;

import com.gitee.feizns.dynamic.function.TryCatch;
import lombok.SneakyThrows;

import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * 仿JS Promise实现
 * @author feizns
 * @since 2025/4/18
 */
public class Promise<T> implements Task<T> {

    /**
     * 前途
     */
    private final CompletableFuture<T> future;

    /**
     * 可完成未来
     * @return {@link CompletableFuture }<{@link T }>
     */
    public CompletableFuture<T> completableFuture() {
        return future;
    }

    /**
     * 承诺
     */
    public Promise() {
        this(new CompletableFuture<>());
    }

    /**
     * 承诺
     * @param value 值
     */
    public Promise(T value) {
        this(CompletableFuture.completedFuture(value));
    }

    /**
     * 承诺
     * @param supplier 供应商
     */
    public Promise(Supplier<T> supplier) {
        this(CompletableFuture.supplyAsync(supplier));
    }

    /**
     * 承诺
     * @param runnable 可运行
     */
    @SuppressWarnings("unchecked")
    public Promise(Runnable runnable) {
        this((CompletableFuture<T>) CompletableFuture.runAsync(runnable));
    }

    /**
     * 承诺
     * @param future 前途
     */
    public Promise(CompletableFuture<T> future) {
        this.future = future;
    }

    /**
     * 然后
     * @param consumer 消费者
     * @return {@link Promise }<{@link Void }>
     */
    public Promise<Void> then(Consumer<T> consumer) {
        return new Promise<>(this.future.thenAcceptAsync(consumer));
    }

    /**
     * 然后
     * @param supplier 供应商
     * @return {@link Promise }<{@link Void }>
     */
    public <R> Promise<R> then(Supplier<R> supplier) {
        return new Promise<>(this.future.thenApplyAsync(e -> supplier.get()));
    }

    /**
     * 然后
     * @param runnable 可运行
     * @return {@link Promise }<{@link Void }>
     */
    public Promise<Void> then(Runnable runnable) {
        return new Promise<>(this.future.thenRunAsync(runnable));
    }

    /**
     * 然后
     * @param function 功能
     * @return {@link Promise }<{@link Void }>
     */
    public <R> Promise<R> then(Function<T, ? extends R> function) {
        return new Promise<>(this.future.thenApplyAsync(function));
    }

    /**
     * 抓住
     * @param function 消费者
     * @return {@link Promise }<{@link T }>
     */
    public Promise<T> catches(Function<Throwable, ? extends T> function) {
        return new Promise<T>(this.future.exceptionally(function));
    }

    /**
     * 抓住
     * @param function 消费者
     * @return {@link Promise }<{@link T }>
     */
    public Promise<T> catches(Consumer<Throwable> function) {
        this.future.exceptionally(ex -> {
            function.accept(ex);
            return null;
        });
        return this;
    }

    /**
     * 无论如何都执行 并返回一个新值
     * @return {@link Promise }<{@link R }>
     */
    public <R> Promise<R> lastly(BiFunction<? super T, Throwable, ? extends R> fn) {
        return new Promise<>(this.future.handleAsync(fn));
    }

    /**
     * 完成
     * @param value 值
     * @return {@link Promise }<{@link T }>
     */
    public boolean complete(T value) {
        return this.future.complete(value);
    }

    /**
     * 拒绝
     * @param ex 异常
     * @return {@link Promise }<{@link T }>
     */
    public boolean reject(Throwable ex) {
        return this.future.completeExceptionally(ex);
    }

    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        return this.future.cancel(mayInterruptIfRunning);
    }

    /**
     * 获取
     * @return {@link T }
     */
    public T join() {
        return this.future.join();
    }

    /**
     * 获取
     * @return {@link T }
     */
    public T await() {
        return this.future.join();
    }

    /**
     * 获取
     * @return {@link T }
     */
    @SneakyThrows
    public T get() {
        return this.future.get();
    }

    /**
     * 获取
     * @return {@link T }
     */
    @SneakyThrows
    public T get(Duration duration) {
        return this.future.get(duration.getSeconds(), TimeUnit.SECONDS);
    }

    /**
     * 获取
     * @param valueIfAbsent 值如果缺席
     * @return {@link T }
     */
    @SneakyThrows
    public T getNow(T valueIfAbsent) {
        return this.future.getNow(valueIfAbsent);
    }

    @Override
    public boolean isDone() {
        return this.future.isDone();
    }

    @Override
    public boolean isCancelled() {
        return this.future.isCancelled();
    }

    @Override
    public boolean isRejected() {
        return this.future.isCompletedExceptionally();
    }

    @Override
    public boolean isFulfilled() {
        return this.future.isDone() && !isRejected() && !isCancelled();
    }

    @Override
    public boolean isPending() {
        return !isDone() && !isCancelled();
    }

    /**
     * 创建一个Promise
     * @return {@link Promise }<{@link T }>
     */
    public static <T> Promise<T> of() {
        return new Promise<>();
    }

    /**
     * 创建一个Promise
     * @param value 值
     * @return {@link Promise }<{@link T }>
     */
    public static <T> Promise<T> of(T value) {
        return new Promise<>(value);
    }

    /**
     * 创建一个Promise
     * @param supplier 供应商
     * @return {@link Promise }<{@link T }>
     */
    public static <T> Promise<T> of(Supplier<T> supplier) {
        return new Promise<>(supplier);
    }

    /**
     * 创建一个Promise（通过回调完成）
     * @param consumer 消费者
     * @return {@link Promise }<{@link T }>
     */
    public static <T> Promise<T> of(Consumer<Task<T>> consumer) {
        Promise<T> result = of();
        consumer.accept(result);
        return result;
    }

    /**
     * 创建一个Promise
     * @param runnable 可运行
     * @return {@link Promise }<{@link Void }>
     */
    public static Promise<Void> of(Runnable runnable) {
        return new Promise<>(runnable);
    }

    /**
     * 创建一个Promise
     * @param future 前途
     * @return {@link Promise }<{@link Void }>
     */
    public static <T> Promise<T> of(CompletableFuture<T> future) {
        return new Promise<>(future);
    }

    /**
     * 任意执行完即可
     * @param supplier 供应商
     * @return {@link Promise }<{@link T }>
     */
    @SafeVarargs
    public static <T> Promise<T> any(Supplier<T>... supplier) {
        @SuppressWarnings("unchecked")
        CompletableFuture<T> any = (CompletableFuture<T>) CompletableFuture.anyOf(Arrays.stream(supplier).map(CompletableFuture::supplyAsync).toArray(CompletableFuture[]::new));
        return new Promise<>(any);
    }

    /**
     * 任意执行完即可
     * @param promises 承诺
     * @return {@link Promise }<{@link T }>
     */
    @SafeVarargs
    public static <T> Promise<T> any(Promise<T>... promises) {
        @SuppressWarnings("unchecked")
        CompletableFuture<T> any = (CompletableFuture<T>) CompletableFuture.anyOf(Arrays.stream(promises).map(Promise::completableFuture).toArray(CompletableFuture[]::new));
        return new Promise<>(any);
    }

    /**
     * 等待全部都执行完
     * @param supplier 供应商
     * @return {@link Promise }<{@link List }<{@link T }>>
     */
    @SafeVarargs
    public static <T> Promise<List<T>> all(Supplier<T>... supplier) {
        return Promise.of(Arrays.stream(supplier).map(CompletableFuture::supplyAsync).map(CompletableFuture::join).collect(Collectors.toList()));
    }

    /**
     * 等待全部都执行完
     * @param supplier 供应商
     * @return {@link Promise }<{@link List }<{@link T }>>
     */
    @SafeVarargs
    public static <T> Promise<List<T>> all(Promise<T>... supplier) {
        return Promise.of(Arrays.stream(supplier).map(Promise::join).collect(Collectors.toList()));
    }

    /**
     * 返回一个延时的Promise
     * @param duration 期间
     * @return {@link Promise }<{@link T }>
     */
    public static <T> Promise<Void> setTimeout(Duration duration) {
        return new Promise<>(() -> { TryCatch.of(() -> Thread.sleep(duration.toMillis())); return null; });
    }

}
